package com.mm.cloud.lease.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mm.cloud.common.core.enums.DeleteEnum;
import com.mm.cloud.common.core.enums.OperationEnum;
import com.mm.cloud.common.core.exception.BaseException;
import com.mm.cloud.common.core.result.Result;
import com.mm.cloud.common.core.result.ResultConstants;
import com.mm.cloud.common.core.result.ResultUtil;
import com.mm.cloud.common.redis.annotation.DistributionLock;
import com.mm.cloud.common.security.annotation.ParameterCheck;
import com.mm.cloud.common.security.helper.LoginUserHelper;
import com.mm.cloud.common.security.loginuser.LoginUser;
import com.mm.cloud.lease.dto.housing.form.DeleteHousingDTO;
import com.mm.cloud.lease.dto.housing.form.SaveHousingDTO;
import com.mm.cloud.lease.dto.housing.form.UpdateHousingDTO;
import com.mm.cloud.lease.dto.housing.query.QueryHousingDTO;
import com.mm.cloud.lease.entity.Housing;
import com.mm.cloud.lease.mapper.HousingMapper;
import com.mm.cloud.lease.service.IHousingService;
import com.mm.cloud.lease.service.impl.convert.housing.HousingConvert;
import com.mm.cloud.lease.vo.housing.HousingPageVO;
import com.mm.cloud.lease.vo.housing.HousingVO;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 房源 服务实现类
 * </p>
 *
 * @author mr
 * @since 2025-06-30
 */
@Service
public class HousingServiceImpl extends ServiceImpl<HousingMapper, Housing> implements IHousingService {

    @Override
    @ParameterCheck
    @DistributionLock(key = "HOUSING", paramName = "#dto.housingCode", isReturn = true)
    public Result<Long> saveHousing(SaveHousingDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        // 校验房源编号
        this.checkHousingCode(loginUser.getCompanyId(), null, dto.getHousingCode(), OperationEnum.ADD);
        // 新增房源
        Housing housing = HousingConvert.convert(dto);
        housing.setCompanyId(loginUser.getCompanyId());
        housing.setRoomCount(0);
        housing.setRestRoomCount(0);
        housing.setTotalFloor(0);
        housing.setCreaterId(loginUser.getUserId());
        this.save(housing);
        return ResultUtil.success(housing.getId());
    }

    @Override
    @ParameterCheck
    @DistributionLock(key = "HOUSING", paramName = "#dto.id", isReturn = true)
    public Result<String> updateHousing(UpdateHousingDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        // 校验房源编号
        this.checkHousingCode(loginUser.getCompanyId(), dto.getId(), dto.getHousingCode(), OperationEnum.UPDATE);
        // 修改房源
        Housing housing = HousingConvert.convert(dto);
        housing.setUpdaterId(loginUser.getUserId());
        this.updateById(housing);
        return ResultUtil.success();
    }

    @Override
    @ParameterCheck
    @DistributionLock(key = "HOUSING:DELETE", paramName = "#dto.id", isReturn = true)
    public Result<String> deleteHousing(DeleteHousingDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();

        // 查询房源信息
        Housing housing = this.getHousing(loginUser.getCompanyId(), dto.getId());

        // 房源已是回收站删除状态
        if (DeleteEnum.RECYCLE_DELETE.getStatus().equals(housing.getIsDelete()) && DeleteEnum.RECYCLE_DELETE.getStatus().equals(dto.getIsDelete())) {
            return ResultUtil.fail("数据已删除");
        }

        // 房源已是永久删除状态
        if (DeleteEnum.DELETE.getStatus().equals(housing.getIsDelete()) && DeleteEnum.RECYCLE_DELETE.getStatus().equals(dto.getIsDelete())) {
            return ResultUtil.fail("数据已删除");
        }

        // 房源已是永久删除状态
        if (DeleteEnum.DELETE.getStatus().equals(housing.getIsDelete()) && DeleteEnum.DELETE.getStatus().equals(dto.getIsDelete())) {
            return ResultUtil.fail("数据已删除");
        }

        // 删除房源
        Housing updateHousing = new Housing();
        updateHousing.setId(dto.getId());
        updateHousing.setIsDelete(dto.getIsDelete());
        updateHousing.setUpdaterId(loginUser.getUserId());
        this.updateById(housing);
        return ResultUtil.success();
    }

    @Override
    @ParameterCheck
    public Result<HousingVO> getHousing(Long id) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        Housing housing = this.getAssertHousing(loginUser.getCompanyId(), id);
        HousingVO housingVO = HousingConvert.convert(housing);
        return ResultUtil.success(housingVO);
    }

    @Override
    public Result<List<HousingPageVO>> getHousingList(QueryHousingDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        dto.setCompanyId(loginUser.getCompanyId());
        IPage<HousingPageVO> page = this.baseMapper.getHousingList(new Page<>(dto.getPage(), dto.getLimit()), dto);
        return ResultUtil.success(page.getRecords(), page.getTotal());
    }

    /**
     * 获取房源
     *
     * @param companyId 公司id
     * @param id        id
     * @return Housing
     */
    private Housing getAssertHousing(Long companyId, Long id) {
        Housing housing = this.getHousing(companyId, id);
        if (!DeleteEnum.NOT_DELETE.getStatus().equals(housing.getIsDelete())) {
            throw new BaseException(ResultConstants.QUERY_NOT_FOUND_DATA);
        }
        return housing;
    }

    /**
     * 获取房源
     *
     * @param companyId 公司id
     * @param id        id
     * @return Housing
     */
    private Housing getHousing(Long companyId, Long id) {
        Assert.notNull(companyId, "companyId is null");
        Assert.notNull(id, "id is null");
        Housing housing = this.getOne(Wrappers.<Housing>lambdaQuery()
                .eq(Housing::getId, id)
                .eq(Housing::getCompanyId, companyId));
        if (Objects.isNull(housing)) {
            throw new BaseException(ResultConstants.QUERY_NOT_FOUND_DATA);
        }
        return housing;
    }

    /**
     * 校验房源编号
     *
     * @param companyId     公司id
     * @param id            id
     * @param housingCode   房源编号
     * @param operationEnum 操作枚举
     */
    private void checkHousingCode(Long companyId, Long id, String housingCode, OperationEnum operationEnum) {
        Assert.notNull(companyId, "companyId is null");
        Assert.notNull(housingCode, "housingCode is null");
        Housing housing = this.getOne(Wrappers.<Housing>lambdaQuery()
                .eq(Housing::getHousingCode, housingCode)
                .eq(Housing::getCompanyId, companyId)
                .ne(Housing::getIsDelete, DeleteEnum.DELETE.getStatus()));
        if (Objects.nonNull(housing)) {
            if (OperationEnum.ADD.equals(operationEnum)) {
                throw new BaseException("房源编号已被使用");
            }
            if (OperationEnum.UPDATE.equals(operationEnum)) {
                if (!housing.getId().equals(id)) {
                    throw new BaseException("房源编号已被使用");
                }
            }
        }
    }
}
